﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Hirham.OpenMI.Sdk.Backbone;
using Hirham.OpenMI.Sdk.Buffer;
using Hirham.OpenMI.Sdk.Spatial;
using OpenMI.Standard;

namespace Hirham.OpenMI.Engine
{
  /// <summary>
  /// HirhamLC - the OpenMI linkable component, by extending the convenience LinkableEngine 
  /// </summary>


  public class HirhamLC : Hirham.OpenMI.Sdk.Wrapper.LinkableEngine
  {

    internal HirhamEngine _hirhamEngine;

    internal double[] mappingmatrix { get; private set; }

    public HirhamLC()
    {
      _hirhamEngine = new HirhamEngine();
      _hirhamEngine.hirhamLC = this;
    }

    ///// <summary>
    ///// Overriding <see cref="ILinkableComponent.AddLink"/>, in order to obtain
    ///// information on the links being added.
    ///// Revised implementation by MAD; Martin Drews (mard@dtu.dk)
    ///// </summary>
    public override void AddLink(ILink newLink)
    {

      // If the Hirham component is the target, we need to set up
      // the interpolation routines
      if (newLink.TargetComponent == this)
      {

        IElementSet sourceSet = newLink.SourceElementSet;
        IElementSet targetSet = newLink.TargetElementSet;

        if (mappingmatrix == null)
        // The source set always has to be of type XYPolygon
        //                 sourceSet.ElementType == ElementType.XYPolygon && newLink.TargetQuantity.ID == "tsl"
        // sourceSet.ElementType == ElementType.XYPolygon &&
        // This is potentially only relevant for some quantities
        // newLink.TargetQuantity.ID == "XXX"
        // MAD: The test on the TargetQuantity.ID ensures that the mapping matrix is only saved once
        //              )
        {

          ElementMapper mapper = new ElementMapper();

          // Find the index of the PolygonToPolygon.WeightedSum mapper
          ArrayList methods = mapper.GetAvailableMethods(sourceSet.ElementType, targetSet.ElementType);
          int weightedSumIndex = methods.IndexOf("Weighted Sum");
          // int weightedSumIndex = methods.IndexOf("Weighted Mean");

          // Only set up if the PolygonToPolygon.WeightedSum is available
          if (weightedSumIndex >= 0)
          {

            // Create a new (temporary mapper)
            mapper.Initialise(methods[weightedSumIndex].ToString(), sourceSet, targetSet);

            // Create fraction vector
            IMatrix<double> matrix = mapper.MappingMatrix;
            double[] fraction = new double[matrix.RowCount];
            for (int i = 0; i < matrix.RowCount; i++)
            {
              for (int j = 0; j < matrix.ColumnCount; j++)
              {
                fraction[i] += matrix[i, j];
              }
            }

            mappingmatrix = fraction;

          }
        }
      }
      // Add the link as usual.
      base.AddLink(newLink);
    }


    protected override void SetEngineApiAccess()
    {
      _engineApiAccess = _hirhamEngine;
    }


  }
}
